<?php declare(strict_types=1);

namespace think\msg\platform;

use SplObserver;
use SplSubject;
use think\msg\msg\Msg;
use think\msg\MsgContext;
use think\msg\MsgException;

abstract class MsgPlatform implements SplObserver
{
    /**
     * 延迟到子类中去实现
     */
    const NAME = null;

    /**
     * @var array 平台自己的配置参数
     */
    protected $config;

    /**
     * @var MsgContext
     */
    protected $context;

    /**
     * @throws MsgException
     */
    public function __construct(MsgContext $context, array $config)
    {
        $this->checkSubClass();
        $this->checkConfig($config);
        $this->config = $config;
        $this->context = $context;
    }

    public final function update(SplSubject $subject)
    {
        /** @var MsgContext $subject */
        $this->send($subject->getMsg());
    }

    abstract protected function send(Msg $msg): void;

    /**
     * 检查配置参数格式，必填参数是否缺少
     * @param array $config
     * @return void
     */
    private function checkConfig(array $config)
    {
    }

    /**
     * 检查子类是否继承了抽象类，必须实现的参数和方法是否实现
     * @return void
     * @throws MsgException
     */
    private function checkSubClass()
    {
        $class = static::class;
        if (empty(static::NAME)) {
            throw new MsgException(sprintf('The %s class must implement the NAME property', $class));
        }
    }
}
